#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include <netinet/in.h>

#include<event2/event.h>
#include<event2/bufferevent.h>

//读回调
void read_cb(struct bufferevent* bev, void* arg)
{
    //读缓冲区数据
    char buf[1024] = {0};
    bufferevent_read(bev, buf, sizeof(buf));
    printf("current buf is %s\n", buf);

    // char* ptr = "123456\n";
    // bufferevent_write(bev, ptr, strlen(ptr)+1);
    printf("数据发送完成。。。\n");
}
//写回调
void write_cb(struct bufferevent* bev, void* arg)
{
    printf("write callback\n");
}

void event_cb(struct bufferevent* bev, short event, void* arg)
{
    if (event & BEV_EVENT_EOF) {
        printf("BEV_EVENT_EOF\n");
    } else if (event & BEV_EVENT_ERROR) {
        printf("BEV_ERROR\n");
    } else if (event & BEV_EVENT_CONNECTED) {
        printf("BEV_EVENT_CONNECTED\n");
        return;
    }
    //释放资源
    bufferevent_free(bev);
}

//终端输入事件，将数据发送给服务端
void read_terminal(int fd, short what, void* arg)
{
    //读终端中的数据
    char buf[1024] = {0};
    int len = read(fd, buf, sizeof(buf));

    struct bufferevent* bev = (struct bufferevent*)arg;
    bufferevent_write(bev, buf, len+1);
}


int main()
{
    //创建事件处理框架
    struct event_base* base = event_base_new();

    //创建事件
    //连接服务端 fd;
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    //绑定fd到事件中去
    struct bufferevent* bev = NULL;
    bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    //连接服务器
    //准备sockaddr
    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_port = htons(8765);
    evutil_inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
    bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv));


    //给缓冲区设置回调函数
    bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
    //设置读缓冲区为可用的,默认写是可用的
    bufferevent_enable(bev, EV_READ);

    //接收键盘输入的事件
    //创建一个新事件
    struct event* ev = event_new(base, STDIN_FILENO,
            EV_READ | EV_PERSIST,
            read_terminal, bev);
    //添加到事件框架中 event_base
    event_add(ev, NULL); //参数2表示超时时间设置


    //启动事件循环
    event_base_dispatch(base);

    //释放资源
    event_base_free(base);

    return 0;
}